home *** CD-ROM | disk | FTP | other *** search
/ Nebula 2 / Nebula Two.iso / Apps / DevTools / eText5 / Source / eTLink.subproj / eTLink.m < prev    next >
Encoding:
Text File  |  1995-02-11  |  9.5 KB  |  319 lines

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //    FILENAME:    eTLink.m 
  3. //    SUMMARY:    Implementation of link buttons in eText documents
  4. //    SUPERCLASS:    Object:eTImage
  5. //    INTERFACE:    None
  6. //    PROTOCOLS:    <Annotation,HTMDSupport,ASCIISupport,LaTeXSupport,Tool,
  7. //                InspectableTarget>
  8. //    AUTHOR:        Rohit Khare
  9. //    COPYRIGHT:    (c) 1994 California Institure of Technology, eText Project
  10. ///////////////////////////////////////////////////////////////////////////////
  11. //    DESCRIPTION
  12. //        Does its job by holding doc/anchorIDs and yelling at NXApp.
  13. ///////////////////////////////////////////////////////////////////////////////
  14. //    HISTORY
  15. //    10/30/94:    Modified to support <InspectableTarget>
  16. //    07/21/94:    Revamped for PR1 and eTImage[Component] support
  17. //    07/09/94:    URLRep added by RK and TRZ (Removed 7/21)
  18. //    07/07/94:    Rewritten as subclass of imageAnnotation
  19. //    07/03/94:    Added eTLinkUI integration for image-links.
  20. //  06/17/94:   HTMDSupport added. RK and TRZ
  21. //    02/04/94:    Created. First actual implementation.
  22. ///////////////////////////////////////////////////////////////////////////////
  23.  
  24. #import "eTLink.h"
  25. #define _eTLinkVERSION    10
  26.  
  27. @implementation eTLink
  28. //    long    anchorID;
  29. //    long    docID;
  30. //    etfLink    theLink;
  31. //    NXAtom    URLRep;
  32.  
  33. + toolAwake:theApp
  34. {
  35.     [theApp   registerAnnotation: [eTLink class] 
  36.                             name: "eTLink"
  37.                     RTFDirective: "eTLink"
  38.                        menuLabel: NULL
  39.                          menuKey: '\0'
  40.                         menuIcon: (NXImage *) nil];
  41.     [theApp registerType:NXCreateFileContentsPboardType("etfd") for:[eTLink class]];
  42.     [theApp registerType:NXCreateFileContentsPboardType("etfLink") for:[eTLink class]];
  43.     return self;
  44. }
  45.  
  46. - init
  47. {
  48.     [super init];
  49.     
  50.     docID = anchorID = 0;
  51.     theLink.docID = theLink.anchorID = theLink.docTitle = theLink.anchorTitle 
  52.         = NXUniqueString("");
  53.     [self setImageComponent:[eTImageComponent newImageNamed:"NXLinkButton"]];
  54.     [self setAltImageComponent:[eTImageComponent newImageNamed:"NXLinkButtonH"]];
  55.     [self setDraggable:YES];
  56.     return self;
  57. }
  58.  
  59. - free 
  60. {
  61.     return self = [super free];
  62. }
  63. - setImageComponent:newImageComponent
  64. {
  65.     const char *name;
  66.     
  67.     name = [[newImageComponent theImage] name];
  68.     if (name && !strcmp(name,"NXLinkButton"))
  69.         usesButtonStyle = NO;
  70.     else
  71.         usesButtonStyle = YES;
  72.     return [super setImageComponent:newImageComponent];
  73. }
  74. - initFromPboard:thePB inDoc:theDoc linked:(BOOL) linked
  75. {
  76.     NXAtom     types[5];
  77.     char    *data;
  78.     int        len;
  79.  
  80.     [super    initFromPboard:thePB inDoc:theDoc linked: linked];
  81.     [self init];
  82.     types[0] = NXCreateFileContentsPboardType("etfLink");
  83.     types[1] = NXCreateFileContentsPboardType("etfd");
  84.     types[2] = NXCreateFileContentsPboardType(ANY_TYPE);
  85.     types[3] = NXFilenamePboardType;
  86.     types[4] = [thePB findAvailableTypeFrom:types num:4];
  87.  
  88.     if (!types[4]) return self;
  89.     if (types[4]) {
  90.         [thePB readType:NXFilenamePboardType data:&data length:&len];
  91.         if (index(data,'\t')) *(index(data,'\t'))=0;
  92.         [self initFromFile:data];
  93.         [thePB deallocatePasteboardData:data length:len];
  94.     } else {
  95.         NXLogError("%s got fcontents without fnamepboard! %s instead.",
  96.                     [[self class] name], types[4]);
  97.     }
  98.     return self;
  99. }
  100.  
  101. - initFromFile: (const char *) theFile
  102. {
  103.     id    theTable;
  104.  
  105.     [self init];
  106.     if (!strcmp("etfLink", rindex(theFile, '.')+1)) {
  107.         theTable = [[NXStringTable alloc] init];
  108.         if ([theTable readFromFile:theFile]) {
  109.             sscanf([theTable valueForStringKey:DOCID], "%x", &docID);
  110.             sscanf([theTable valueForStringKey:ANCHORID], 
  111.                         "%x", &anchorID);
  112.             theLink.docID = NXUniqueString([theTable valueForStringKey:DOCID]);
  113.             theLink.anchorID = NXUniqueString([theTable valueForStringKey:ANCHORID]);
  114.             theLink.docTitle = NXUniqueString([theTable valueForStringKey:DOCTITLE]);
  115.             theLink.anchorTitle = NXUniqueString([theTable valueForStringKey:ANCHORTITLE]);
  116.         }
  117.         theTable = [[theTable empty] free]; // free even if read from file failed
  118.     } else if (!strcmp(ETFD_EXT, rindex(theFile, '.')+1)) {
  119.         // find a docID for this file, stash it away
  120.         theTable = [[[eTDocInfo alloc] init] readComponentFromPath:theFile];
  121.         if (theTable){
  122.             docID = [theTable docID];
  123.             anchorID = 0;
  124.             theLink.docID = NXUniqueString([theTable docIDStr]);
  125.             theLink.anchorID = NXUniqueString("0");    
  126.             theLink.anchorTitle = theLink.docTitle = NXUniqueString([theTable title]);
  127.             theTable = [theTable free];
  128.         }
  129.     } else { 
  130.         NXLogError("eTLink asked to init from:%s; cannot.", theFile);
  131.     }
  132.     return self;
  133. }
  134.         
  135. - readRichText:(NXStream *)stream forView:view 
  136. {
  137.     int i;
  138.     char buf[MAXPATHLEN];
  139.     
  140.     NXScanf(stream, "%d ", &i);
  141.     if (i != _eTLinkVERSION) {
  142.         // bad version block.
  143.         NXLogError("eTLink found unparseable version %d at position %d",
  144.                     i, NXTell(stream));
  145.         return nil;
  146.     }
  147.  
  148.     NXScanf(stream, "%s ", buf);
  149.     theLink.docID = NXUniqueString(buf);
  150.     sscanf(theLink.docID, "%x", &docID);
  151.  
  152.     NXScanf(stream, "%s", buf);
  153.     theLink.anchorID = NXUniqueString(buf);
  154.     sscanf(theLink.anchorID, "%x", &anchorID);
  155.  
  156.     NXScanf(stream, "%d", &i); NXGetc(stream); //space-eater
  157.     if (i) NXRead(stream, buf, i);
  158.     buf[i] = 0;
  159.     theLink.docTitle = NXUniqueString(buf);
  160.  
  161.     NXScanf(stream, "%d", &i); NXGetc(stream); //space-eater
  162.     if (i) NXRead(stream, buf, i);
  163.     buf[i] = 0;
  164.     theLink.anchorTitle = NXUniqueString(buf);
  165.     
  166.     NXGetc(stream); // extra space char.
  167.     [super readRichText:stream forView:view];
  168.     return self;
  169. }
  170.  
  171. - writeRichText:(NXStream *)stream forView:view
  172. {
  173.     id dI=nil;
  174.     
  175.     // maintain docID-docTitle consistency
  176.     dI = [eTDocInfo findDocInfo:docID];
  177.     if (dI) theLink.docTitle= NXUniqueString([dI docTitle]);
  178.     NXPrintf(stream, "%d %s %s %d %s %d %s ", _eTLinkVERSION,
  179.                 theLink.docID, theLink.anchorID, 
  180.                 strlen(theLink.docTitle), theLink.docTitle,
  181.                 strlen(theLink.anchorTitle), theLink.anchorTitle);
  182.     [super writeRichText:stream forView:view];
  183.     return self;
  184. }
  185.  
  186. - writeASCIIRef:(NXStream *)stream forView:view
  187. {
  188.     if(*theLink.docID) {
  189.         if(theLink.anchorID && anchorID)
  190.             NXPrintf(stream, "See %y in %y [%s in %s]\n\t", theLink.anchorTitle, theLink.docTitle, theLink.anchorID, theLink.docID);
  191.         else
  192.             NXPrintf(stream, "See %y [%s]\n\t", theLink.docTitle, theLink.docID);
  193.     } 
  194.     [super writeASCIIRef:stream forView:view];
  195.     return self;
  196. }
  197.  
  198. - writeLaTeX:(NXStream*)stream forView:view
  199. {    
  200.     [super writeLaTeX:stream forView:view];
  201.     if(*theLink.docID) {
  202.         if(theLink.anchorID && anchorID)
  203.             NXPrintf(stream, "\n\\footnote{See %w in %w [%w in %w]}\n", theLink.anchorTitle, theLink.docTitle, theLink.anchorID, theLink.docID);
  204.         else
  205.             NXPrintf(stream, "\n\\footnote{See %w [%w]}\n", theLink.docTitle, theLink.docID);
  206.     } 
  207.     return self;
  208. }
  209.  
  210. - writeHTML:(NXStream *)stream forView:view
  211.     char tmp[MAXPATHLEN];
  212.     
  213.     id theDocInfo = [eTDocInfo findDocInfo:docID];
  214.     if(!theDocInfo) return self;
  215.     
  216.     if(*theLink.docID) {
  217.         strcpy(tmp, [theDocInfo docPath]);
  218.         *rindex(tmp,'.')=0;
  219.         NXPrintf(stream,"<A HREF=\"../%V."HTMD_EXT"/"HTML_INDEX,rindex(tmp,'/')+1);
  220.         if(anchorID) NXPrintf(stream,"#%s", theLink.anchorID);
  221.         NXPrintf(stream, "\">");
  222. //        if (theLink.anchorTitle && *theLink.anchorTitle) {
  223. //            NXPrintf(stream,"\"><%v>", theLink.anchorTitle);
  224.  
  225.         [super writeHTML:stream forView:view];
  226.         NXPrintf(stream,"</A>");
  227.  
  228. //        }
  229. //        else 
  230. //            NXPrintf(stream,"\"><Click Here></A>");
  231.     }
  232.     return self;
  233. }
  234. #define NXLINK "NXLinkButton"
  235. #define NXLINK_GIF NXLINK".gif"
  236. - writeComponentToPath:(NXAtom)path inFormat:(int) theFormat
  237. {
  238.     const char *name;
  239.     
  240.     if(!etDoc)    NXLogError("etDoc is nil at %s %u",__FILE__,__LINE__);
  241.     name = [[imageComponent theImage] name];
  242.     if ((theFormat == HTMD_FMT) && name && !strcmp(name,NXLINK)) {
  243.         char cmd[2*MAXPATHLEN];
  244.  
  245.         sprintf(cmd,"%s/"NXLINK_GIF, [[NXBundle mainBundle] directory]);
  246.         if (!access(cmd, F_OK|R_OK)) {
  247.           sprintf(cmd,"cp -rp \"%s/"NXLINK_GIF"\" \"%s/"NXLINK_GIF"\"", 
  248.                  [[NXBundle mainBundle] directory], path);
  249.           system(cmd);
  250.           [etDoc registerComponent:NXLINK_GIF];
  251.         } else {
  252.             [super writeComponentToPath:path inFormat:theFormat];
  253.         }
  254.     } else
  255.         [super writeComponentToPath:path inFormat:theFormat];
  256.     return self;
  257. }
  258.  
  259. - doubleClick2:sender
  260. {
  261.     if (docID && [eTDocInfo findDocInfo:docID]) {
  262.         [[NXApp etApp] openID:docID];
  263.         [[[objc_lookUpClass("eTBookmarkBinder") new] bookmarkForID:anchorID] highlight:sender];
  264.     } else {
  265.         NXRunAlertPanel("eTLink", "Could not locate docID %x","OK", NULL, NULL,docID);
  266.     }
  267.     return self;
  268. }
  269.  
  270. - doubleClick:(NXEvent *) e
  271. {
  272.     [self perform:@selector(doubleClick2:) with:self afterDelay:0 
  273.         cancelPrevious:YES];
  274.     return self;
  275. }
  276.  
  277. - inspect:(NXEvent *) e
  278. {
  279.     [[NXApp inspector] inspect:self];
  280.     return self;
  281. }
  282. - (id <Inspectable>) inspectableDelegate {
  283.     return [[eTLinkUI new] setAnnotation:self]; }
  284.  
  285. - (NXAtom)anchorTitle 
  286.     {return ((theLink.anchorTitle) ? theLink.anchorTitle : "");}
  287. - (NXAtom)anchorID
  288.     {return ((theLink.anchorID) ? theLink.anchorID : "");}
  289. - (NXAtom)docTitle
  290.     {return ((theLink.docTitle) ? theLink.docTitle : "");}
  291. - (NXAtom)docID
  292.     {return ((theLink.docID) ? theLink.docID : "");}
  293.  
  294. - drag: (Pasteboard *)draggingPboard image:(NXImage **)proxyImage
  295. {
  296.     id         theTable;
  297.     char    filename[MAXPATHLEN];
  298.     
  299.     theTable = [[NXStringTable alloc] init];
  300.     [theTable insertKey:DOCID 
  301.         value: NXCopyStringBuffer(theLink.docID)];
  302.     [theTable insertKey:ANCHORID
  303.         value: NXCopyStringBuffer(theLink.anchorID)];
  304.     [theTable insertKey:DOCTITLE value:
  305.         NXCopyStringBuffer(theLink.docTitle)];
  306.     [theTable insertKey:ANCHORTITLE value: 
  307.         NXCopyStringBuffer(theLink.anchorTitle)];
  308.     sprintf(filename, "/tmp/%s.etfLink", theLink.anchorTitle);
  309.     [theTable writeToFile:filename];
  310.     theTable = [[theTable empty] free];
  311.  
  312.     [draggingPboard declareTypes:&NXFilenamePboardType num:1 owner:nil];
  313.     [draggingPboard writeType: NXFilenamePboardType data: filename
  314.                     length: strlen(filename)];
  315.     *proxyImage = [[eTImageComponent newImageNamed:"NXLinkButton"] theImage];
  316.     return self;
  317. }
  318. @end